#region Copyright (C) 2007 Jens Winter

//Copyright (C) 2007 Jens Winter

//This library is free software; you can redistribute it and/or
//modify it under the terms of the GNU Lesser General Public
//License as published by the Free Software Foundation; either
//version 2.1 of the License, or (at your option) any later version.

//This library is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//Lesser General Public License for more details.

//You should have received a copy of the GNU Lesser General Public
//License along with this library; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#endregion

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Flynn.Core;
using Flynn.Core.ConnectionFactories;

namespace Flynn
{
    public class ConnectionFactoriesCollector
    {
        public IDictionary<string, string> CollectConnectionFactories(string directory)
        {
            IDictionary<string, string> connectionFactories = new Dictionary<string, string>();

            CollectConnectionFactoriesInDirectory(directory, connectionFactories);

            return connectionFactories;
        }

        private static void CollectConnectionFactoriesInDirectory(string directory, IDictionary<string, string> connectionFactories)
        {
            string[] files = Directory.GetFiles(directory, "*.dll", SearchOption.TopDirectoryOnly);
            foreach (string file in files)
            {
                CollectConnectionFactoriesInFile(file, connectionFactories);
            }
        }

        private static void CollectConnectionFactoriesInFile(string file, IDictionary<string, string> connectionFactories)
        {
            Assembly assembly = null;
            try
            {
                assembly = Assembly.LoadFrom(file);
            }
            catch
            {
            }

            if (assembly != null)
                CollectConnectionFactoriesInAssembly(assembly, connectionFactories);
        }

        private static void CollectConnectionFactoriesInAssembly(Assembly assembly, IDictionary<string, string> connectionFactories)
        {
            Type[] types = assembly.GetTypes();
            foreach (Type type in types)
            {
                if (!type.IsAbstract && typeof(IConnectionFactory).IsAssignableFrom(type) && type != typeof(SafeConnectionFactory))
                {
                    object[] connectionFactoriesAttributes = type.GetCustomAttributes(typeof(ConnectionFactoryAttribute), false);
                    if (connectionFactoriesAttributes.Length > 0)
                        connectionFactories.Add(((ConnectionFactoryAttribute)connectionFactoriesAttributes[0]).FriendlyName, type.AssemblyQualifiedName);
                    else
                    {
                        if (type.Name.EndsWith("ConnectionFactory"))
                            connectionFactories.Add(type.Name.Substring(0, type.Name.Length - "ConnectionFactory".Length), type.AssemblyQualifiedName);
                        else
                            connectionFactories.Add(type.AssemblyQualifiedName, type.AssemblyQualifiedName);
                    }
                }
            }
        }
    }
}